﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;

using System.Threading;
using System.IO;
using Microsoft.Speech.Recognition;
using Microsoft.Speech.AudioFormat;
using System.Diagnostics;
using SpeechLib;


namespace nuiWare.nuIDE
{
    /// <summary>
    /// Interaction logic for MyControl.xaml
    /// </summary>
    public partial class MyControl : UserControl
    {

        private SpeechRecognitionEngine sre=null;
        private KinectSensor sensor = null;
        private Stream stream = null; 

        public MyControl()
        {
            InitializeComponent();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions")]
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if (!button1.Content.ToString().Equals("Stop Voice Command"))
            {
                button1.Content = "Stop Voice Command";

                StartCommand();

            }
            else
            {
                button1.Content = "Start Voice Command";

                StopCommand(); 
            }

        }


        private void StartCommand()
        {

            if (sensor == null)
            {
                sensor = (from sensorToCheck in KinectSensor.KinectSensors where sensorToCheck.Status == KinectStatus.Connected select sensorToCheck).FirstOrDefault();
            } 
           if (sensor == null)
            {
                ResponseText.Text = 
                        "No Kinect sensors are attached to this computer or none of the ones that are\n" +
                        "attached are \"Connected\".\n" +
                        "Attach the KinectSensor and restart this application.\n" +
                        "If that doesn't work run SkeletonViewer-WPF to better understand the Status of\n" +
                        "the Kinect sensors.\n\n" +
                        "Press any key to continue.\n";

                
                return;
            }


            sensor.Start();

            // Obtain the KinectAudioSource to do audio capture
            KinectAudioSource source = sensor.AudioSource;
            source.EchoCancellationMode = EchoCancellationMode.None; // No AEC for this sample
            source.AutomaticGainControlEnabled = false; // Important to turn this off for speech recognition

            RecognizerInfo ri = GetKinectRecognizer();

            if (ri == null)
            {
                 ResponseText.Text = "Could not find Kinect speech recognizer. Please refer to the sample requirements.";
                return;
            }

            Console.WriteLine("Using: {0}", ri.Name);

            // NOTE: Need to wait 4 seconds for device to be ready right after initialization
            int wait = 4;
            while (wait > 0)
            {
                ResponseText.Text =string.Format("Device will be ready for speech recognition in {0} second(s).\r", wait--);
                Thread.Sleep(1000);
            }

            if(sre == null)
            {
             sre = new SpeechRecognitionEngine(ri.Id);
            }

                var commands = new Choices();
                commands.Add("Open Power Shell");
                commands.Add("Open Google");
                commands.Add("Open Bing");
                commands.Add("Open Note Pad");
                commands.Add("Build Solution");
                commands.Add("Close Solution");
                commands.Add("Computer, Deploy");
                commands.Add("Computer, Close All");
                commands.Add("Computer, Save All");
                commands.Add("Computer, Quit"); 

                var gb = new GrammarBuilder { Culture = ri.Culture };

                // Specify the culture to match the recognizer in case we are running in a different culture.                                 
                gb.Append(commands);

                // Create the actual Grammar instance, and then load it into the speech recognizer.
                var g = new Grammar(gb);

                sre.LoadGrammar(g);
                sre.SpeechRecognized += SreSpeechRecognized;
                sre.SpeechHypothesized += SreSpeechHypothesized;
                sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected;

                if (stream == null)
                {
                    stream = source.Start();
                }

                
                    sre.SetInputToAudioStream(
                        stream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));

                    sre.RecognizeAsync(RecognizeMode.Multiple);
                 
                
            

           

        }


        private void StopCommand()
        {


            if (sre != null)
            {
                sre.RecognizeAsyncStop();

            }



            if (sensor != null)
            {
                sensor.Stop();
            }
        }


        private static RecognizerInfo GetKinectRecognizer()
        {
            Func<RecognizerInfo, bool> matchingFunc = r =>
            {
                string value;
                r.AdditionalInfo.TryGetValue("Kinect", out value);
                return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) && "en-US".Equals(r.Culture.Name, StringComparison.InvariantCultureIgnoreCase);
            };
            return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
        }


        #region Event Methods


        private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
        {

            

            ResponseText.Text = "\nSpeech Rejected"; 

            

            if (e.Result != null)
            {
               
            }
        }


        private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
        {
            ResponseText.Text = string.Format("\rSpeech Hypothesized: \t{0}", e.Result.Text);
        }

        private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            if (e.Result.Confidence >= 0.7)
            {
                ResponseText.Text =string.Format("\nSpeech Recognized: \t{0}\tConfidence:\t{1}", e.Result.Text, e.Result.Confidence);

              
                switch (e.Result.Text.ToLower())
                {
                    case "open power shell":
                        {
                            SpVoice voice = new SpVoice();

                            voice.Speak("Opening powershell."); 
                            
                            

                            Process powershell = new Process();

                            powershell.StartInfo.FileName = "powershell.exe";

                            powershell.Start();

                        }
                        break;
                    case "open google":
                        {
                            SpVoice voice = new SpVoice();

                            voice.Speak("Opening google."); 

                            Process ie = new Process();

                            ie.StartInfo.FileName = "iexplore.exe";
                            ie.StartInfo.Arguments = "http://www.google.com";
                            ie.Start();

                        }
                        break;
                    case "open bing":
                        {

                            SpVoice voice = new SpVoice();

                            voice.Speak("Opening bing."); 

                            Process ie = new Process();

                            ie.StartInfo.FileName = "iexplore.exe";
                            ie.StartInfo.Arguments = "http://www.bing.com";
                            ie.Start();
                        }
                        break;
                    case "open note pad":
                        {
                            SpVoice voice = new SpVoice();

                            voice.Speak("Opening Note pad"); 

                            Process notePad = new Process();

                            notePad.StartInfo.FileName = "notepad.exe";

                            notePad.Start();

                        }
                        break;
                    case "build solution":
                        {

                            var dte = (EnvDTE.DTE)nuIDEPackage.GetGlobalService(typeof(EnvDTE.DTE));

                            if (dte != null && dte.Solution != null && dte.Solution.SolutionBuild != null)
                            {
                                dte.Solution.SolutionBuild.Build();

                                
                            }
                          
                        }
                        break;
                    case "close solution":
                        {
                            var dte = (EnvDTE.DTE)nuIDEPackage.GetGlobalService(typeof(EnvDTE.DTE));

                            if (dte != null && dte.Solution != null && dte.Solution.SolutionBuild != null)
                            {
                                dte.Solution.Close(false);


                            }
                        }
                        break;

                    case "computer, deploy":
                        {
                            var dte = (EnvDTE.DTE)nuIDEPackage.GetGlobalService(typeof(EnvDTE.DTE));

                            if (dte != null && dte.Solution != null && dte.Solution.SolutionBuild != null)
                            {
                                dte.Solution.SolutionBuild.Deploy(false);

                                dte.Documents.CloseAll(EnvDTE.vsSaveChanges.vsSaveChangesPrompt); 
                            }
                        }
                        break;   

                    case "computer, close all":
                        {
                            var dte = (EnvDTE.DTE)nuIDEPackage.GetGlobalService(typeof(EnvDTE.DTE));


                            dte.Documents.CloseAll(EnvDTE.vsSaveChanges.vsSaveChangesPrompt);


                            
                        }

                        break;

                    case "computer, save all":
                        {

                            var dte = (EnvDTE.DTE)nuIDEPackage.GetGlobalService(typeof(EnvDTE.DTE));


                            dte.Documents.SaveAll();

                            
                        }

                        break;

                    case "computer, quit":
                        {

                            var dte = (EnvDTE.DTE)nuIDEPackage.GetGlobalService(typeof(EnvDTE.DTE));

                            dte.Quit(); 


                        }
                        break;

                    
                    
                }

            }
            else
            {
                ResponseText.Text =string.Format("\nSpeech Recognized but confidence was too low: \t{0}", e.Result.Confidence);
              
            }

            
        }




        #endregion 

    }
}